package nz.co.listit.TaxiValet;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.Bundle;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.ToggleButton;

public class StatusActivity extends ListItResClient {
	private static final int HELLO_ID = 1;

	/* 5 MINUTES (make value bigger to save battery & money) */
	private static final int LOCATION_TIME_ACCURACY = 1000 * 60 * 5;

	/* 200 METRES (make value bigger to save battery & money) */
	private static final int LOCATION_DISTANCE_ACCURACY = 200;

	/* here define activity results */
	private static final int RESULT_PREFERENCE_VISITED = 0;
	private static final int RESULT_JOB_HANDLED = 1;

	// this is the dialog that is displayed when a taxi job notification is
	// received
	private Dialog _jobAlert = null;
	private ToggleButton _btnStatus;
	private TextView _tvStatus;
	private boolean _isBusy = false;
	private String _MyCurrentIPAddress = null;
	private WifiLock _wifiLock;
	private volatile ListItSocketListener _listItPortListener;

	// used to send a global "Taxi" notification that appears on the top of the
	// phone
	private NotificationManager _notificationMgr;

	// variables that allow us to get a GPS fix
	private Location _currentLocation;
	private LocationManager _locationManager;
	private LocationListener _locationListener = new LocationListener() {

		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub

		}

		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub

		}

		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub

		}

		public void onLocationChanged(Location location) {
			if (isBetterLocation(location, _currentLocation)) {
				_currentLocation = location;
				uploadLocationToServer(_currentLocation);
			}
		}
	};
	protected boolean _terminating = false;

	private void ListenToLocationChanges(boolean enable) {
		// get saved preference
		if (enable) {
			SharedPreferences sp = PreferenceManager
					.getDefaultSharedPreferences(this);
			boolean useNetworkProvider = sp.getBoolean("location_wifi", true);
			boolean useGPSProvider = sp.getBoolean("location_gps", true);

			// Register the listener with the Location Manager to receive
			int timeAccuracy;
			int distanceAccuracy;

			if (_debug) {
				/*
				 * if we're in debug mode we want to update more often to see if
				 * the GPS is actually working. This is also good for demos.
				 */
				timeAccuracy = 0;
				distanceAccuracy = 5; // meters
			} else {
				/*
				 * But if we're in normal mode, we need to conserve battery and
				 * limit network chit-chat to save the driver $$$
				 */
				timeAccuracy = LOCATION_TIME_ACCURACY;
				distanceAccuracy = LOCATION_DISTANCE_ACCURACY; // meters
			}

			if (useNetworkProvider) {
				_locationManager.requestLocationUpdates(
						LocationManager.NETWORK_PROVIDER, timeAccuracy,
						distanceAccuracy, _locationListener);
			}

			if (useGPSProvider) {
				_locationManager.requestLocationUpdates(
						LocationManager.GPS_PROVIDER, 0, 10, _locationListener);
			}
		} else {
			_locationManager.removeUpdates(_locationListener);
		}
	}

	private void HandleNewJobRequest(Intent intent, Boolean usingSocket) {
		// if the job alert is showing then we don't want to show it again
		if (StatusActivity.this._jobAlert != null)
			return;

		// Say Taxi! and show the alert on the statusbar
		StatusActivity.this.DoStatusBarNotification();

		_jobAlert = new Dialog(StatusActivity.this);

		// create a dismiss listener so that we can identify if _jobAlert is
		// displaying or not
		_jobAlert.setOnDismissListener(new OnDismissListener() {
			public void onDismiss(DialogInterface dialog) {
				StatusActivity.this._jobAlert = null;
			}
		});

		_jobAlert.setContentView(R.layout.jobnotification);

		String title;
		if (usingSocket)
			title = _debug ? "New Job Alert via Socket" : "New Job Alert!";
		else
			title = _debug ? "New Job Alert via C2DM" : "New Job Alert!";

		_jobAlert.setTitle(title);
		_jobAlert.setCancelable(true);

		Button btn = (Button) _jobAlert.findViewById(R.id.btnJobAccept);
		btn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				StatusActivity.this.showJobActivity();

				if (StatusActivity.this._jobAlert != null)
					StatusActivity.this._jobAlert.dismiss();
			}
		});

		btn = (Button) _jobAlert.findViewById(R.id.btnJobDecline);
		btn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				StatusActivity.this.decineJob();

				if (StatusActivity.this._jobAlert != null)
					StatusActivity.this._jobAlert.dismiss();
			}
		});

		_jobAlert.show();
	}

	private void HandleServerMessage(Intent intent) {
		// must be a message from the server
		final Dialog dialog = new Dialog(StatusActivity.this);
		dialog.setContentView(R.layout.servermesage);
		dialog.setTitle("Message from List-It server");

		TextView text = (TextView) dialog
				.findViewById(R.id.tvServerMessageText);
		String extra = intent.getStringExtra("msg");
		text.setText(extra);

		dialog.setCancelable(true);
		Button btn = (Button) dialog.findViewById(R.id.btnServerMessageOK);
		btn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				dialog.cancel();
			}
		});

		dialog.show();
	}

	private void HandleConnectivityChange(Intent intent) {
		final String ipAddress = getLocalIpAddress();

		// if the IP address of the device has changed then update the server
		if ((ipAddress != null) && (_MyCurrentIPAddress != ipAddress)) {
			new Thread(new Runnable() {
				public void run() {
					ListItServerClient ltClient = new ListItServerClient();
					List<NameValuePair> qparams = new ArrayList<NameValuePair>();

					// add device ID
					qparams.add(new BasicNameValuePair("deviceID",
							StatusActivity.this.getDeviceID()));

					// add ip address
					qparams.add(new BasicNameValuePair("ipAddress", ipAddress));

					// call web service
					ltClient.queryListItService("UpdateIPAddress", qparams);

					_MyCurrentIPAddress = ipAddress;
				}
			}).start();
		}
	}

	/**
	 * Embed a receiver so we can be notified when there is a new job
	 */
	private BroadcastReceiver c2mdRegisteredReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {

			if (intent.getAction().equals(
					ListItC2dmReceiver.INTENT_C2DM_NEW_JOB)) {
				HandleNewJobRequest(intent, false);
			} else if (intent.getAction().equals(
					ListItC2dmReceiver.INTENT_C2DM_SERVER_MESSAGE)) {
				HandleServerMessage(intent);
			} else if (intent.getAction().equals(
					ConnectivityManager.CONNECTIVITY_ACTION)) {
				HandleConnectivityChange(intent);
			} else if (intent.getAction().equals(
					ListItSocketListener.INTENT_LISTIT_SERVER_PING)) {
				HandleNewJobRequest(intent, true);
			}
			/*
			 * else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { if
			 * (!_listItPortListener.isAlive()) _listItPortListener.start(); }
			 * else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
			 * if (_listItPortListener.isAlive()) _listItPortListener.stop(); }
			 */
		}
	};

	private void DoStatusBarNotification() {
		// instantiate the notification
		String s = getString(R.string.STaxiAlert);
		Notification notification = new Notification(R.drawable.masaya, s,
				System.currentTimeMillis());
		notification.flags |= Notification.FLAG_AUTO_CANCEL;

		// define the Notification's expanded message and Intent
		Context context = getApplicationContext();
		CharSequence contentTitle = getString(R.string.SNewJobTitle);
		CharSequence contentText = getString(R.string.SNewJobText);

		/*
		 * this three lines of code doesn't really do anything. If you want to
		 * set focus to the current activity you need to specify singleTask in
		 * the manifest file.
		 */
		final Intent notificationIntent = new Intent(this, StatusActivity.class);
		notificationIntent.setAction(Intent.ACTION_MAIN);
		notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);

		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				notificationIntent, 0);

		notification.setLatestEventInfo(context, contentTitle, contentText,
				contentIntent);
		notification.sound = Uri
				.parse("android.resource://nz.co.listit.TaxiValet/"
						+ R.raw.taxi);
		_notificationMgr.notify(HELLO_ID, notification);
	}

	private void setStatus(boolean busy) {
		if (busy) {
			this._tvStatus.setText(R.string.Busy);
			this._tvStatus.setTextColor(getResources().getColor(
					R.color.BusyColor));
		} else {
			this._tvStatus.setText(R.string.Available);
			this._tvStatus.setTextColor(getResources().getColor(
					R.color.AvailableColor));
		}

		_isBusy = busy;
	}

	private void decineJob() {
		_progDlg = ProgressDialog.show(StatusActivity.this, "",
				"Processing. Please wait...", true);

		// remove the status bar notification
		NotificationManager notificationMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		notificationMgr.cancelAll();

		ListItServerClient ltClient = new ListItServerClient();

		List<NameValuePair> qparams = new ArrayList<NameValuePair>();

		try {
			// add device ID
			qparams.add(new BasicNameValuePair("deviceID", this.getDeviceID()));
			// call web service
			JSONObject result = ltClient.queryListItService("DeclineJob",
					qparams);

			Message msg = new Message();
			msg.what = result.getInt(KEY_SERVER_RET_CODE);
			msg.obj = result;
			handler.sendMessage(msg);

		} catch (JSONException e) {
			Log.e(TAG,
					String.format(FMT_ERROR, "onTrashJob", KEY_SERVER_RET_CODE));
		}
	}

	private void logout() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage("Are you sure you want to logout of TaxiValet?")
				.setCancelable(false)

				.setPositiveButton("Yes",
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {

								_progDlg = ProgressDialog.show(
										StatusActivity.this, "",
										"Processing. Please wait...", true);

								new Thread(new Runnable() {
									public void run() {
										ListItServerClient ltClient = new ListItServerClient();
										List<NameValuePair> qparams = new ArrayList<NameValuePair>();

										// add device ID
										qparams.add(new BasicNameValuePair(
												"deviceID", StatusActivity.this
														.getDeviceID()));

										// call web service
										JSONObject result = ltClient
												.queryListItService("Logout",
														qparams);

										Message msg = new Message();
										try {
											msg.what = result
													.getInt("return_code");
											msg.obj = result;
											StatusActivity.this.handler
													.sendMessage(msg);
										} catch (JSONException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
									}
								}).start();
							}
						})

				.setNegativeButton("No", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int id) {
						dialog.cancel();
					}
				});
		AlertDialog alert = builder.create();
		alert.show();
	}

	private void showJobActivity() {
		ListenToLocationChanges(false);

		// stop getting updates to location
		_locationManager.removeUpdates(_locationListener);

		Intent intent = new Intent(Intent.ACTION_VIEW);

		Bundle bundle = new Bundle();
		bundle.putBoolean(KEY_SERVER_DEBUG_TAXI, _debug);

		intent.setClassName(this, JobActivity.class.getName());
		intent.putExtras(bundle);

		startActivityForResult(intent, RESULT_JOB_HANDLED);
	}

	private void uploadLocationToServer(final Location location) {
		new Thread(new Runnable() {
			public void run() {
				ListItServerClient ltClient = new ListItServerClient();
				List<NameValuePair> qparams = new ArrayList<NameValuePair>();

				// add device ID
				qparams.add(new BasicNameValuePair("deviceID",
						StatusActivity.this.getDeviceID()));

				// add longitude
				qparams.add(new BasicNameValuePair("longitude", Double
						.toString(location.getLongitude())));

				// add latitude
				qparams.add(new BasicNameValuePair("latitude", Double
						.toString(location.getLatitude())));

				// call web service
				JSONObject result = ltClient.queryListItService(
						"UpdateLocation", qparams);

				Message msg = new Message();
				try {
					msg.what = result.getInt(KEY_SERVER_RET_CODE);
					msg.obj = result;
					StatusActivity.this.handler.sendMessage(msg);
				} catch (JSONException e) {
					Log.e(TAG, String.format(FMT_ERROR, "StatusActivity.run",
							KEY_SERVER_RET_CODE));
				}
			}
		}).start();
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
			return provider2 == null;
		}
		return provider1.equals(provider2);
	}

	/**
	 * Determines whether one Location reading is better than the current
	 * Location fix
	 * 
	 * @param location
	 *            The new Location that you want to evaluate
	 * @param currentBestLocation
	 *            The current Location fix, to which you want to compare the new
	 *            one
	 */
	protected boolean isBetterLocation(Location location,
			Location currentBestLocation) {
		if (currentBestLocation == null) {
			// A new location is always better than no location
			return true;
		}

		// Check whether the new location fix is newer or older
		long timeDelta = location.getTime() - currentBestLocation.getTime();
		boolean isSignificantlyNewer = timeDelta > LOCATION_TIME_ACCURACY;
		boolean isSignificantlyOlder = timeDelta < -LOCATION_TIME_ACCURACY;
		boolean isNewer = timeDelta > 0;

		// If it's been more than two minutes since the current location, use
		// the new location
		// because the user has likely moved
		if (isSignificantlyNewer) {
			return true;
			// If the new location is more than two minutes older, it must be
			// worse
		} else if (isSignificantlyOlder) {
			return false;
		}

		// Check whether the new location fix is more or less accurate
		int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
				.getAccuracy());
		boolean isLessAccurate = accuracyDelta > 0;
		boolean isMoreAccurate = accuracyDelta < 0;
		boolean isSignificantlyLessAccurate = accuracyDelta > 200;

		// Check if the old and new location are from the same provider
		boolean isFromSameProvider = isSameProvider(location.getProvider(),
				currentBestLocation.getProvider());

		// Determine location quality using a combination of timeliness and
		// accuracy
		if (isMoreAccurate) {
			return true;
		} else if (isNewer && !isLessAccurate) {
			return true;
		} else if (isNewer && !isSignificantlyLessAccurate
				&& isFromSameProvider) {
			return true;
		}
		return false;
	}

	@Override
	protected void onOKResult(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();
	}

	// called on DEVICE_NOT_LOGGED_IN
	@Override
	protected void onDeviceNotLoggedIn(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setClassName(this, LoginActivity.class.getName());
		startActivity(intent);
		this.finish();
	}

	// called on LOGGED_OUT
	@Override
	protected void onLoggedOut(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		if (!_terminating) {
			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.setClassName(this, LoginActivity.class.getName());
			startActivity(intent);
		}

		ListenToLocationChanges(false);
		StatusActivity.this.finish();
	}

	// called on STATUS_BUSY
	@Override
	protected void onStatusBusy(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		this.setStatus(true);
		ListenToLocationChanges(false);
	}

	// called on STATUS_AVAILABLE
	@Override
	protected void onStatusAvailable(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		this.setStatus(false);
		ListenToLocationChanges(true);
	}

	// called on CONNECTION_ERROR
	@Override
	protected void onConnectionError(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		String serverMsg = "";
		try {
			serverMsg = json.getString(KEY_SERVER_MESSAGE);
		} catch (JSONException e) {
			Log.e(TAG, String.format(FMT_ERROR, "onConnectionError",
					KEY_SERVER_MESSAGE));
		}

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage("Connection failed." + serverMsg)
				.setTitle("Connection Error")

				.setCancelable(false)

				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int d) {
						dialog.cancel();
					}
				});

		AlertDialog alert = builder.create();
		alert.show();

		// make sure we set the button state as it was before
		_btnStatus.setChecked(!_isBusy);
	}

	@Override
	protected void onServerError(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		String serverMsg = "";
		try {
			serverMsg = json.getString(KEY_SERVER_MESSAGE);
		} catch (JSONException e) {
			Log.e(TAG, String.format(FMT_ERROR, "onServerError",
					KEY_SERVER_MESSAGE));
		}

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(serverMsg).setTitle("Server Error")

		.setCancelable(false)

		.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int d) {
				dialog.cancel();
			}
		});

		AlertDialog alert = builder.create();
		alert.show();

		// make sure we set the button state as it was before
		_btnStatus.setChecked(!_isBusy);
	}

	@Override
	// called on UNKNOWN_ERROR
	protected void onUnknownError(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(
				"Ops something happened that I cannot explained.  \nIf it keeps happening please contact List-It.")
				.setTitle("Unknown Error")

				.setCancelable(false)

				.setPositiveButton("Yes",
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int d) {
								dialog.cancel();
							}
						});

		AlertDialog alert = builder.create();
		alert.show();

		// make sure we set the button state as it was before
		_btnStatus.setChecked(!_isBusy);
	}

	// called on HAS_JOB
	@Override
	protected void hasJob(JSONObject json) {
		showJobActivity();
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case RESULT_PREFERENCE_VISITED:
			// reset location listening code

			// first let's remove all listening events
			ListenToLocationChanges(false);

			// if driver is avaiable, run the location logic again with the new
			// preference
			if (!_isBusy)
				ListenToLocationChanges(true);
			break;

		case RESULT_JOB_HANDLED:
			// after a job, then we are "available"; hence re-enable GPS
			ListenToLocationChanges(true);

		default:
			break;
		}
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		/*
		 * IMPORTANT!!! You need this code here because this stops the onCreate
		 * to get called when the phone goes into sleep mode. When the onCreate
		 * is called while the phone is going to sleep, the activity will crash!
		 */
		super.onConfigurationChanged(newConfig);
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.status);

		// setup location manager to get updates to user location
		_locationManager = (LocationManager) this
				.getSystemService(Context.LOCATION_SERVICE);

		// set debug flag
		Bundle bundle = this.getIntent().getExtras();
		_debug = bundle.getBoolean(KEY_SERVER_DEBUG_TAXI);

		// set global exception handler, if device is in debug mode
		if (_debug) {
			Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(
					this));
		}

		// show debug indicator
		TextView tvDemo = (TextView) findViewById(R.id.tvDemo);
		if (_debug) {
			tvDemo.setVisibility(View.VISIBLE);
		} else {
			tvDemo.setVisibility(View.INVISIBLE);
		}

		this._btnStatus = (ToggleButton) findViewById(R.id.btnStatus);
		this._tvStatus = (TextView) findViewById(R.id.tvStatus);

		_notificationMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

		ListenToLocationChanges(true);

		// acquire Wi-Fi lock so that our radio will not turn off. This is
		// important for ListItServerThread!
		WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		_wifiLock = manager.createWifiLock(TAG);
		_wifiLock.acquire();

		_listItPortListener = new ListItSocketListener(this);
		_listItPortListener.start();

		new Thread(new Runnable() {
			public void run() {
				ListItServerClient ltClient = new ListItServerClient();
				List<NameValuePair> qparams = new ArrayList<NameValuePair>();

				// add device ID
				qparams.add(new BasicNameValuePair("deviceID",
						StatusActivity.this.getDeviceID()));

				// call web service
				JSONObject result = ltClient.queryListItService("HasActiveJob",
						qparams);

				Message msg = new Message();
				try {
					msg.what = result.getInt(KEY_SERVER_RET_CODE);
					msg.obj = result;
					StatusActivity.this.handler.sendMessage(msg);
				} catch (JSONException e) {
					Log.e(TAG, String.format(FMT_ERROR, "StatusActivity.run",
							KEY_SERVER_RET_CODE));
				}
			}
		}).start();
	}

	@Override
	protected void onDestroy() {
		unregisterReceiver(c2mdRegisteredReceiver);
		super.onDestroy();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {

		// we want to inform the user before we terminate the application
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			logout();
			return true;
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}

	@Override
	public void onSaveInstanceState(Bundle savedInstanceState) {
		// Save UI state changes to the savedInstanceState.
		// This bundle will be passed to onCreate if the process is
		// killed and restarted.

		savedInstanceState.putBoolean("isBusy", _isBusy);
		super.onSaveInstanceState(savedInstanceState);
	}

	@Override
	public void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		boolean isBusy = savedInstanceState.getBoolean("isBusy");
		setStatus(isBusy);
		ListenToLocationChanges(!isBusy);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.status_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.checkForJob:
			showJobActivity();

			return true;
		case R.id.signout:
			logout();
			return true;

		case R.id.showPreferences:
			startActivityForResult(new Intent(this, SettingsActivity.class),
					RESULT_PREFERENCE_VISITED);

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@Override
	public void onResume() {
		super.onResume();

		// register for C2DM actions
		IntentFilter filter = new IntentFilter();
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_NEW_JOB);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_SERVER_MESSAGE);
		filter.addAction(ListItSocketListener.INTENT_LISTIT_SERVER_PING);
		filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		filter.addAction(Intent.ACTION_SCREEN_OFF);
		filter.addAction(Intent.ACTION_SCREEN_ON);

		this.registerReceiver(c2mdRegisteredReceiver, filter);
	}

	public void onStatusClick(View v) {
		_progDlg = ProgressDialog.show(StatusActivity.this, "",
				"Processing. Please wait...", true);

		new Thread(new Runnable() {
			public void run() {
				ListItServerClient ltClient = new ListItServerClient();
				List<NameValuePair> qparams = new ArrayList<NameValuePair>();

				// add device ID
				qparams.add(new BasicNameValuePair("deviceID",
						StatusActivity.this.getDeviceID()));

				// add status
				qparams.add(new BasicNameValuePair("isBusy", _btnStatus
						.isChecked() ? "false" : "true"));

				// call web service
				JSONObject result = ltClient.queryListItService("SetStatus",
						qparams);

				Message msg = new Message();
				try {
					msg.what = result.getInt(KEY_SERVER_RET_CODE);
					msg.obj = result;
					StatusActivity.this.handler.sendMessage(msg);
				} catch (JSONException e) {
					Log.e(TAG, String.format(FMT_ERROR, "StatusActivity.run",
							KEY_SERVER_RET_CODE));
				}
			}
		}).start();
	}

	public void onLogOff(View v) {
	}

	@Override
	public void run() {
		// do nothing
	}

	@Override
	public void finish() {
		_wifiLock.release();
		_listItPortListener.interrupt();
		_listItPortListener = null;
		super.finish();
	}
}
